#include <jni.h>
#include <string>


#include "pthread.h"
#include "AndroidLog.h"

pthread_t thread;

void *normalCallBack(void *data) {

    LOGD("create normal thread from c++");

    pthread_exit(&thread);
}


extern "C"
JNIEXPORT void JNICALL
Java_com_renfei_jnithread_util_PThread_createNormalThread(JNIEnv *env, jobject instance) {

    pthread_create(&thread, NULL, normalCallBack, NULL);
}


//C++ 队列
#include "queue"
#include "unistd.h"

pthread_t produc;//生产者线程
pthread_t custom;//消费者线程

pthread_mutex_t mutex;  //线程锁
pthread_cond_t cond;    //条件变量

std::queue<int> queue;//声明队列

bool exit = false;//退出标志

void *produceCallBack(void *data) {

    while (!exit) {
        pthread_mutex_lock(&mutex);//加锁

        queue.push(1);
        LOGD("生产者生产了一个产品,通知消费者消费,产品数量为%d", queue.size());
        pthread_cond_signal(&cond);//通知消费者可以进行消费了
        pthread_mutex_unlock(&mutex);//解锁

        sleep(5);//生产者5秒生产一个产品
    }

    pthread_exit(&produc);
}

void *customCallBack(void *data) {
    while (!exit) {

        pthread_mutex_lock(&mutex);//消费者消费时也是对quenu进行操作，也要进行加锁

        if (queue.size() > 0) {
            queue.pop();
            LOGD("消费者消费了一个产品,产品数量剩余%d", queue.size());
        } else {

            LOGD("没有产品可以消费了,等待中。。。。");
            pthread_cond_wait(&cond, &mutex);   //等待时，系统会自动解锁

        }
        pthread_mutex_unlock(&mutex);
        usleep(1000 * 500);//消费者  多久消费一个产品  单位为V秒
    }

    pthread_exit(&custom);

}


extern "C"
JNIEXPORT void JNICALL
Java_com_renfei_jnithread_util_PThread_createProduceAndConsumption(JNIEnv *env, jobject instance) {


    //初始化数据，给队列添加10条数据
    for (int i = 0; i < 10; ++i) {
        queue.push(i);
    }

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);


    pthread_create(&produc, NULL, produceCallBack, NULL);
    pthread_create(&custom, NULL, customCallBack, NULL);

}


#include "JavaListener.h"

JavaVM *jvm;
JavaListener *javaListener;


pthread_t childThread;


void *onChildThreadCallBack(void *data) {

    JavaListener *javaListener1 = (JavaListener *) data;
    javaListener1->onError(1, 101, "c++ call java method from child thread");
}

extern "C"
JNIEXPORT void JNICALL
Java_com_renfei_jnithread_util_PThread_callBackFromC(JNIEnv *env, jobject instance) {

    javaListener = new JavaListener(jvm, env, env->NewGlobalRef(instance));
    /**
     * 主线程中调用
     */
//    javaListener->onError(0,100,"c++ call java method from main thread");

    /**
     * 创建子线程
     */
    pthread_create(&childThread, NULL, onChildThreadCallBack, NULL);
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *resversed) {
    JNIEnv *env;
    jvm = vm;


    if (vm->GetEnv((void **) (&env), JNI_VERSION_1_6) != JNI_OK) {

        return -1;
    }

    return JNI_VERSION_1_6;
}

